﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace WindowsGame1
{
    class Wall
    {
        Model wall;
        Matrix[] wallTransforms;
        Cell cell;
        CellSide edge;
        Vector3 position;
        BoundingBox boundingBox;
        float rotation;
        int length = 200;
        int height = 40;
        int width = 40;
        Vector3 lowerLeftCorner;
        Vector3 upperRightCorner;

        public Wall(Cell cell, CellSide edge)
        {
            this.cell = cell;
            this.edge = edge;
            position = CalculatePosition();
            boundingBox = FormBoundingBox();
            rotation = (edge == CellSide.TOP || edge == CellSide.BOTTOM) ? 0.0f : 90.0f;
        }

        public void Load(ContentManager content)
        {
            wall = content.Load<Model>("wallstone");
            wallTransforms = new Matrix[wall.Bones.Count];
            wall.CopyAbsoluteBoneTransformsTo(wallTransforms);
        }

        public Matrix[] GetTransforms()
        {
            return wallTransforms;
            }

        private BoundingBox FormBoundingBox()
        {
            Vector3[] wallPoints = new Vector3[2]; // lower-back-left, upper-front-right points

            wallPoints[0] = lowerLeftCorner;
            wallPoints[1] = upperRightCorner;
            
            //Console.Out.WriteLine("Bounding box coordinates for side " + edge + " wall of cell " +
            //    cell.GetX() + ", " + cell.GetY() + ": " + wallPoints[0].ToString() + ", " + wallPoints[1].ToString());

            return BoundingBox.CreateFromPoints(wallPoints);
        }

        public BoundingBox GetBoundingBox()
        {
            return boundingBox;
        }

        private Vector3 CalculatePosition()
        {
            float xPos, yPos, zPos;
            xPos = cell.GetX() * length + length/2; // Gets center of cell's x coordinate (cell(0,0) -> 0*200 + 100 = 100)
            yPos = 0.0f;
            zPos = cell.GetY() * length + length/2; // Gets center of cell's y coordinate
            
            // BEST ONE SO FAR
            float num = 4.0f;
            switch (edge)
            {
                case CellSide.TOP: // WORKS, with all these magic numbers
                    zPos += (length / 2) + (width / 2);
                    xPos -= (float)((num / 100.0) * length);
                    lowerLeftCorner.Z = zPos + 3;
                    lowerLeftCorner.X = xPos - (length / 2) - 16;
                    upperRightCorner.Z = zPos - (width * 2) - 3;
                    upperRightCorner.X = xPos + (length / 2) - 10;
                    upperRightCorner.Y = height * 2;
                    break;
                case CellSide.BOTTOM: // WORKS
                    zPos -= (length / 2) - (width / 2);
                    xPos -= (float)((num / 100.0) * length);
                    lowerLeftCorner.Z = zPos - width * 2 - 4;
                    lowerLeftCorner.X = xPos - (length / 2) - 16;
                    upperRightCorner.Z = zPos + 3;
                    upperRightCorner.X = xPos + (length / 2) - 10;
                    upperRightCorner.Y = height * 2;
                    break;
                case CellSide.RIGHT: // WORKS
                    xPos += (length / 2) + (width / 2);
                    zPos -= (float)((num / 22.0) * length);
                    lowerLeftCorner.X = xPos - width * 2 - 4;
                    lowerLeftCorner.Z = zPos - (length / 2) + 10;
                    upperRightCorner.X = xPos + 3;
                    upperRightCorner.Z = zPos + (length / 2) + 16;
                    upperRightCorner.Y = height * 2;
                    break;
                case CellSide.LEFT: // WORKS
                    xPos -= (length / 2) - (width / 2);
                    zPos -= (float)((num / 22.0) * length);
                    lowerLeftCorner.X = xPos - width * 2 - 4;
                    lowerLeftCorner.Z = zPos + (length / 2) + 18;
                    upperRightCorner.X = xPos + (width / 2) - 15;
                    upperRightCorner.Z = zPos - (length / 2) + 10;
                    upperRightCorner.Y = height * 2;
                    break;
            }

            return new Vector3(xPos, yPos, zPos);
        }
        
        public Cell GetCell()
        {
            return cell;
        }

        public CellSide GetEdge()
        {
            return edge;
        }

        internal Vector3 getPosition()
        {
            return position;
        }

        internal void Draw(Matrix world, Matrix view, Matrix projection)
        {
            wall.Root.Transform = world;
            // Look up combined bone matrices for the entire model.
            //wall.CopyAbsoluteBoneTransformsTo(wallTransforms); // Done in load...

            // Draw the model.
            foreach (ModelMesh mesh in wall.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World = wallTransforms[mesh.ParentBone.Index];
                    effect.View = view;
                    effect.Projection = projection;

                    effect.EnableDefaultLighting();
                }

                mesh.Draw();
            }
        }

        internal float getRotation()
        {
            return rotation;
        }
    }
}
